package org.zjvis.datascience.common.etl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.netty.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.zjvis.datascience.common.constant.SqlTemplate;
import org.zjvis.datascience.common.enums.ETLEnum;
import org.zjvis.datascience.common.enums.SubTypeEnum;
import org.zjvis.datascience.common.sql.SqlHelper;
import org.zjvis.datascience.common.util.SqlUtil;
import org.zjvis.datascience.common.util.ToolUtil;
import org.zjvis.datascience.common.vo.TaskVO;

/**
 * @description ETL-Pivot 数据透视表类
 * @date 2021-12-27
 */
public class PivotTable extends BaseETL {
    private static String PIVOT_TABLE_SQL = "select pipeline.sys_func_pivot_table_view_create(%s,%s,%s,%s,%s,%s) res";

    private String rows;

    private String colStr;

    private Integer colSize;

    private String statisticsStr;

    public PivotTable() {
        super(ETLEnum.PIVOT_TABLE.name(), SubTypeEnum.ETL_OPERATE.getVal(),
            SubTypeEnum.ETL_OPERATE.getDesc());
        this.maxParentNumber = 1;
    }

    public void parserConf(JSONObject conf) {
        if (conf.getJSONArray("rows") == null || conf.getJSONArray("cols") == null
            || conf.getJSONArray("statistics") == null) {
            return;
        }

        int flag = 0;
        for (String row:conf.getJSONArray("rows").toJavaList(String.class)) {
            if ( flag==0 ) {
                rows = row;
            } else {
                rows = rows+","+row;
            }
            flag++;
        }
        JSONArray cols = conf.getJSONArray("cols");
        StringBuilder sb= new StringBuilder();
        String tempStr = "";
        if (cols!=null&&cols.size()>0) {
            for (int i=0;i<cols.size();i++) {
                if (i==0) {
                    tempStr = SqlUtil.formatValue(cols.getString(i));
                } else {
                    tempStr = tempStr+","+SqlUtil.formatValue(cols.getString(i));
                }
            }
        }
        colStr = sb.append("array[").append(tempStr).append("]").toString();

        colSize = conf.getIntValue("colSize");

        statisticsStr = resetDuplicateData(conf.getJSONArray("statistics")).toJSONString();
    }

    public static JSONArray resetDuplicateData(JSONArray data) {
        int i = 1;
        if (data==null || data.size()==1) {
            return data;
        } else {
            Set<String> exitData = new HashSet<>();
            for (int k=0;k<data.size();k++) {
                JSONObject statistic = data.getJSONObject(k);
                String tmpStr = statistic.getString("col")+"_"
                    +statistic.getString("method")+"_"
                    +statistic.getString("name");
                String oldName = statistic.getString("name");
                while (exitData.contains(tmpStr)) {
                    tmpStr = tmpStr+i;
                    if (!exitData.contains(tmpStr)) {
                        statistic.put("name",oldName+i);
                        break;
                    }
                    i++;
                }
                exitData.add(tmpStr);
            }
        }
        return data;
    }

    public String initSql(JSONObject conf, List<SqlHelper> sqlHelpers, long timeStamp,
        String engineName) {
        this.engineName = engineName;
        String sql = StringUtil.EMPTY_STRING;
        if (conf.getInteger("colSize")==-1) {
            return sql;
        }
        JSONArray input = conf.getJSONArray("input");
        String table = input.getJSONObject(0).getString("tableName");
        table = ToolUtil.alignTableName(table, timeStamp);
        JSONArray output = conf.getJSONArray("output");
        String outTable = output.getJSONObject(0).getString("tableName") + timeStamp;

        sql = String.format(PIVOT_TABLE_SQL, SqlUtil.formatValue(table), SqlUtil.formatValue(outTable), SqlUtil.formatValue(rows), colStr,colSize,SqlUtil.formatValue(statisticsStr));

        return sql;
    }

    /**
     * 定义输出表格式
     *
     * @param vo
     * @return
     */
    public void defineOutput(TaskVO vo) {
        JSONArray jsonArray = new JSONArray();
        JSONObject jsonObject = vo.getData();
        String tableName = String
            .format(SqlTemplate.VIEW_TABLE_NAME, vo.getPipelineId(), vo.getId());
        JSONObject item = new JSONObject();
        JSONArray output = jsonObject.getJSONArray("output");
        JSONArray tableCols = new JSONArray();
        JSONArray columnTypes = new JSONArray();
        JSONObject semantic = new JSONObject();
        if (output!=null&&!output.isEmpty()) {
            tableCols = output.getJSONObject(0).getJSONArray("tableCols");
            columnTypes = output.getJSONObject(0).getJSONArray("columnTypes");
            semantic = output.getJSONObject(0).getJSONObject("semantic");
        }
        JSONArray input = jsonObject.getJSONArray("input");
        JSONObject numberFormat = input.getJSONObject(0).getJSONObject("numberFormat");
        if (numberFormat != null && tableCols != null && !tableCols.isEmpty()) {
            Set<String> cols = numberFormat.keySet();
            for (String col : cols) {
                if (!tableCols.contains(col)) {
                    numberFormat.remove(col);
                }
            }
        }
        item.put("numberFormat", numberFormat);
        item.put("tableName", tableName);
        item.put("nodeName", vo.getName() == null ? ETLEnum.PIVOT_TABLE.toString() : vo.getName());
        item.put("tableCols", tableCols);
        item.put("columnTypes", columnTypes);
        item.put("semantic", semantic);
        this.setSubTypeForOutput(item);
        jsonArray.add(item);
        jsonObject.put("output", jsonArray);
        vo.setData(jsonObject);
    }

    public void initTemplate(JSONObject data) {
        data.put("rows", new JSONArray());
        data.put("cols", new JSONArray());
        data.put("statistics", new JSONArray());
        data.put("colSize", -1);
        baseInitTemplate(data);
    }
}
